//
// Created by cmo on 2022/3/20.
//

#ifndef JNI_SAFE_QUEUE_TOOL_H
#define JNI_SAFE_QUEUE_TOOL_H

#endif //JNI_SAFE_QUEUE_TOOL_H

#include <iostream>
#include<string>
#include<pthread.h>
#include<queue>
#define OK 1;

using namespace std;

template <typename D>
class SafeQueue
{
private:
    queque<D> data;
    pthread_mutex_t mutex;//为了线程安全定义互斥锁，且不允许有野指针必须初始化和销毁
    pthread_cond_t cond;
public:
    SafeQueue()
    {
        pthread_mutex_init(&mutex,0);
        pthread_cond_init(&cond,0);
    }
    ~SafeQueue()
    {
         pthread_mutex_destory(&mutex);
         pthread_cond_destory(&cond);
    }

    //执行生产
    void produce(D d)
    {
        pthread_mutex_lock(&mutex);
        data.push(d);
        //pthread_cond_signal(&cond);//发出信号，由系统通知挂起的一个线程唤醒，无法控制具体是哪一条线程被唤醒，Java#notify
        pthread_cond_broadcast(&cond);// 广播 对应多个消费者的时候 多个线程等待唤醒所有,Java#notifyAll
        pthread_mutex_unlock(&mutex);
    }

    /**
     * 如果队列中没有数据则不运行
     * @param d 通过传入的引用类型形参返回返回，因为是引用类型，外界访问时该地址对应的值也同步更新
     * @return void
     */
    int consume(D& d)
    {
        /**
         * Java对应的写法
		* synchronized(mutex){wait()}
		*/
        pthread_mutex_lock(&mutex);
        while(data.empty()){//因为可能会被意外唤醒 所以while循环
            ////如果队列无数据则一直阻塞调用出队操作的消费者线程
            ptread_cond_wait(&cond,&mutex);
        }
        d=data.front();//获取队列头的数据
        data.pop();//删除已经消费的数据
        pthread_mutex_unlock(&mutex);
        return OK;
    }
};